package com.tensquare.notice.netty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.tensquare.entity.Result;
import com.tensquare.entity.StatusCode;
import com.tensquare.notice.config.ApplicationContextProvider;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Netty的处理器
 * 与WebSocket整合，处理WebSocket的请求
 */
public class MyWebSocketHandler extends SimpleChannelInboundHandler {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 缓存用户的通道/连接，用户在线时，服务器向浏览器推送消息时要用到
    // key是用户的id 唯一
    public static ConcurrentHashMap<String,Channel> channelMap = new ConcurrentHashMap<String,Channel>();

    /**
     * 收到Websocket发送过来的请求
     * @param ctx 整条管道信息，连接信息
     * @param msg 请求参数：消息内容
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("进入了MyWebSocketHandler处理了：" + msg);
        //做什么？用户登陆后页面加载就触发过来的
        // 完成的任务:
        // 1. 从rabbitmq中取属于这个用户的待推送消息，取出消息的个数即可
        // 2. 为以后当用户线时使用原有的通道进行推送，缓存通道连接
        // 取出用户的id, 通过队列的名称连接rabbitmq, 队列名称（article_subscribe_2）
        // 拼接用户id即可得到队列名称，从而获取mq队列中的消息
        // webSocket的数据类型，前端传过来的数据中包含中户的id, 以json格式过来的
        TextWebSocketFrame webSocketMsg = (TextWebSocketFrame) msg;
        String text = webSocketMsg.text();
        // System.out.println(webSocketMsg.text());
        //{
        //    "userId":"2"
        //}
        String userId = objectMapper.readTree(text).get("userId").asText();

        // 缓存用户的通道
        channelMap.put(userId, ctx.channel());

        // 队列名称
        String queueName = "article_subscribe_" + userId;
        // 访问mq, rabbitAddmin
        RabbitAdmin rabbitAdmin = ApplicationContextProvider.getApplicationContext().getBean(RabbitAdmin.class);
        // 获取队列的信息
        Properties queueProperties = rabbitAdmin.getQueueProperties(queueName);
        int count = 0;
        if(null != queueProperties){
            // 队列存在, 获取队列中消息的个数
            count = (int) queueProperties.get(RabbitAdmin.QUEUE_MESSAGE_COUNT);
        }
        // 构建返回给浏览器的数据{data:{sysNoticeCount:1}}
        Map<String, Integer> resultMap = new HashMap<String,Integer>();
        resultMap.put("sysNoticeCount", count);
        Result result = new Result(true, StatusCode.OK,"查询成功", resultMap);
        // 使用通道写数据，响应给浏览器,
        // 注意：writeAndFlush 必须是WebSocket的类型数据
        ctx.channel().writeAndFlush(new TextWebSocketFrame(objectMapper.writeValueAsString(result)));

        //用户在线,添加队列的监听器,
        if(null != queueProperties) {
            if(count > 0) {
                // 清空消息
                rabbitAdmin.purgeQueue(queueName, true);
            }
            // 取出监听器容器
            SimpleMessageListenerContainer sysNoticeContainer = ApplicationContextProvider.getApplicationContext().getBean("sysNoticeContainer", SimpleMessageListenerContainer.class);
            // 添加监听队列
            sysNoticeContainer.addQueueNames(queueName);
        }
    }
}
